/**
	Copyright (c) 2010 ATTi 
	All rights reserved.
	Author: Michael Shu
	Date: 9/9/2010
*/

public with sharing class AccountTeamController {
	public static String NO_SPLIT = '0.00%';
	public static String TRUE_Val = 'true';
	public static String System_Administrator = 'System Administrator';
	public static Set<String> AllowedProfileNames = new Set<String>{'National Sales Assignment Manager'};
	public static String FULLACCESS = 'Full Access';
	public static String READWRITE = 'Read/Write';
	public static String READONLY = 'Read Only';
	public static String PRIVATESTR = 'Private';
	public static String READ = 'Read';
	public static String EDIT = 'Edit';
	public static String NONE = 'None';
	public static String ALL = 'All';
	public static String OWNER = 'Owner';
	public static String NA = 'n/a';
	private static Map<String, Integer> levels = new Map<String, Integer>{ALL => 3, EDIT => 2, READ => 1, NONE => 0, '' => -1};
	public static Set<String> ROW_REASONS = new Set<String>{'Team', 'Owner', 'Manual'};
	
	public Boolean hasDMLpermssion{get{return checkDMLpermssion();}set;}
	public Boolean isDisplayAccess {get; set;}
	//-------------------------Account Team-------------------------------------------------------------
	public Id accId {get; set;}
	public Boolean hasAccteams {get{return !accTeams.isEmpty();} set;}
	public List<accountTeam> accTeams{
		get{
			List<accountTeam> acc_teams = new List<accountTeam>();
			List<AccountTeamMember> allAccTeams = [select Id, AccountId, UserId, User.Name, User.Profile.Name, TeamMemberRole from AccountTeamMember where AccountId =: accId order by User.Name asc];
			List<AccountShare> allAccShrs = [select UserOrGroupId, AccountAccessLevel, OpportunityAccessLevel, CaseAccessLevel, RowCause from AccountShare where AccountId =: accId and RowCause IN: ROW_REASONS ];
			Map<ID, String> userPermssions = new Map<ID, String>();
			for(AccountShare a_shr : allAccShrs){
				if(a_shr.RowCause == OWNER){
					userPermssions.put(a_shr.UserOrGroupId, FULLACCESS + ';' + READWRITE + ';' + READWRITE);
				}else{
					userPermssions.put(a_shr.UserOrGroupId, trans(a_shr.AccountAccessLevel) + ';' + trans(a_shr.OpportunityAccessLevel) + ';' + trans(a_shr.CaseAccessLevel));
				}
			}
			for(AccountTeamMember a : allAccTeams){
	          	accountTeam new_ateam = new accountTeam();
	          	new_ateam.at = a;
	          	String accShr =  userPermssions.get(a.UserId);
	          	if(a.User.Profile.Name.startsWith(System_Administrator)){
	          		new_ateam.AccountAccessLevel = FULLACCESS;
	          		new_ateam.OpportunityAccessLevel = FULLACCESS;
	          		new_ateam.CaseAccessLevel = FULLACCESS;	
	          	}else if(accShr != null){
	          		String[] ss = accShr.split(';');
	          		new_ateam.AccountAccessLevel = ss[0];
	          		new_ateam.OpportunityAccessLevel = ss[1];
	          		new_ateam.CaseAccessLevel = ss[2];
	          	}else{
	          		new_ateam.AccountAccessLevel = NA;
	          		new_ateam.OpportunityAccessLevel = NA;
	          		new_ateam.CaseAccessLevel = NA;		          		
	          	}
	          	acc_teams.add(new_ateam);
	         }
	         return acc_teams;
	    }
	    set;}
	public class accountTeam {			
		public AccountTeamMember at {get; set;}
		public String AccountAccessLevel {get; set;}
		public String OpportunityAccessLevel {get; set;}
		public String CaseAccessLevel {get; set;}
	}
	//-------------------------opps Team-------------------------------------------------------------
	public Id oppId {get; set;}
	public String answer{get; set;}
	public Boolean hasoppteams {get{return !oppTeams.isEmpty();} set;}
	public Boolean hasAccount {
		get{
			Opportunity o = [select AccountId from Opportunity where Id =: this.oppId limit 1];
			if(o.AccountId != null){
				List<AccountTeamMember> parentAccTeams = [select Id from AccountTeamMember where AccountId =: o.AccountId];
				if(!parentAccTeams.isEmpty()){
					return true;
				}
			}
			return false;
	    }set;
	    }
	public Boolean hasDefaultSalesTeam{
		get{
			ID oppOwnerId = [select OwnerId from Opportunity where Id =: oppId limit 1].OwnerId;
			List<UserTeamMember> defaultOppTeams = [select Id from UserTeamMember where OwnerId =: oppOwnerId];	
			return !defaultOppTeams.isEmpty();	
		}set;
	    }
	public String  editButtonName {get{if(!oppTeams.isEmpty()){return 'Edit All';} return 'Add/Split';} set;}
	public List<oppTeam> oppTeams{
		get{
			List<oppTeam> opp_teams = new List<oppTeam>();
			UpdateOppSalesTeam.updatesalesteam(oppId);
			List<OpportunityTeamMember> allOppTeams = [select Id, OpportunityId, Opportunity.OwnerId, UserId, User.Name, User.Profile.Name, TeamMemberRole,OpportunityAccessLevel from OpportunityTeamMember where OpportunityId =: oppId order by User.Name asc];
			system.debug('testing1'+allOppTeams);
			List<OpportunitySplit> allOppSplits = [select SplitOwnerId, SplitPercentage, SplitAmount, SplitNote from OpportunitySplit where OpportunityId =: oppId];
			Map<ID, OpportunitySplit> splits = new Map<ID, OpportunitySplit>();
			for(OpportunitySplit sp : allOppSplits){
				splits.put(sp.SplitOwnerId,  sp);
			}
			for(OpportunityTeamMember o : allOppTeams){
				oppTeam new_oppteam = new oppTeam();
				new_oppteam.ot = o;
				if(o.User.Profile.Name.startsWith(System_Administrator) || o.UserId == o.Opportunity.OwnerId){
	          		new_oppteam.OpportunityAccessLevel = FULLACCESS;
	          	}else{
	          		new_oppteam.OpportunityAccessLevel = trans(o.OpportunityAccessLevel);	          		
	          	}
	          	new_oppteam.Split = '';
	          	new_oppteam.SplitAmount = '';
	          	new_oppteam.SplitNote = '';
	          	OpportunitySplit opp_sp;
	          	if(splits.containsKey(o.UserId)){
	          		opp_sp = splits.get(o.UserId);
	          		new_oppteam.Split = '' + opp_sp.SplitPercentage + '%';
	          		new_oppteam.SplitAmount = '$' + opp_sp.SplitAmount;
	          		new_oppteam.SplitNote = (opp_sp.SplitNote == null)? '' : opp_sp.SplitNote;
	          	}
	          	opp_teams.add(new_oppteam);
			}
			return opp_teams;
		}
		set;
	}
	public class oppTeam {			
		public OpportunityTeamMember ot {get; set;}
		public String OpportunityAccessLevel {get; set;}
		public String Split{get;set;}
		public String SplitAmount{get;set;}
		public String SplitNote{get;set;}
	}
	//-------------------------------------------------------------------------------------------------
	
	private Boolean checkDMLpermssion(){
		Boolean dmlPermssion = false;
		List<Profile> allowedProfiles = [select Id from Profile where Name IN: AllowedProfileNames or Name like: System_Administrator + '%'];
		if(!allowedProfiles.isEmpty()){
			for(Profile p : allowedProfiles){
				if(p.Id == UserInfo.getProfileId()){	
					dmlPermssion = true;
					break;
				}				
			}
		}
		return dmlPermssion;
	}
		
	
	private String trans(String accessLevel){
		if(accessLevel == READ){
			return READONLY;
		}else if(accessLevel == EDIT){
			return READWRITE;
		}else if(accessLevel == NONE){
			return PRIVATESTR;
		}else if(accessLevel == ALL){
			return FULLACCESS;
		}
		return accessLevel;
	}

	public PageReference displayAccess(){
		isDisplayAccess = true;
		if(this.accId != null){
			addInfo('Account team members may have greater access than defined by their account team membership.');
		}else{
			addInfo('Sales team members may have greater access than defined by their sales team membership.');
		}
		return null;
	}
	
	public PageReference deleteAccTeam(){
		Id delAccTeamId = ApexPages.currentPage().getParameters().get('delAccTeam_Id');
		for(accountTeam a : accTeams){
			if(a.at.Id == delAccTeamId){	
				delete a.at;				
				break;
			}
		}
		PageReference pg = new PageReference('/' + this.accId);
		pg.setRedirect(true);
		return pg;
	}

	public PageReference deleteAllAccTeam(){
		List<AccountTeamMember> delAccTeams = [select Id from AccountTeamMember where AccountId =: accId];
		try{
			delete delAccTeams;
		}catch(Exception ex){
			addError(ex.getMessage());
			GeneralConstants.mailAnyExceptionToMe('VFPageAccountTeam :','VF page : delete all account team Fail', ex);
		}
		return null;
	}	
		
	public PageReference addAccTeam(){
		return null;
	}
			
	public PageReference addDefaultAccTeams(){
		ID accOwnerId = [select OwnerId from Account where Id =: accId limit 1].OwnerId;
		List<UserAccountTeamMember> defaultAccTeams = [select TeamMemberRole, UserId, AccountAccessLevel, OpportunityAccessLevel, CaseAccessLevel from UserAccountTeamMember where OwnerId =: accOwnerId];
		List<AccountTeamMember> newAccTeams = new List<AccountTeamMember>();
		List<AccountShare> upsertAccShrs = new List<AccountShare>();
		if(!defaultAccTeams.isEmpty()){
			List<AccountShare> accShrs = [select AccountAccessLevel, OpportunityAccessLevel, CaseAccessLevel, UserOrGroupId from AccountShare where AccountId =: accId and RowCause IN: ROW_REASONS ];
			Map<ID, AccountShare> userPermssions = new Map<ID, AccountShare>();
			for(AccountShare a_shr : accShrs){
				userPermssions.put(a_shr.UserOrGroupId, a_shr);
			}
			
			for(UserAccountTeamMember u_at : defaultAccTeams){
				AccountTeamMember new_ateam = new AccountTeamMember();
				new_ateam.AccountId = this.accId;
				new_ateam.TeamMemberRole = u_at.TeamMemberRole;
				new_ateam.UserId = u_at.UserId;
				newAccTeams.add(new_ateam);
				
				if(u_at.UserId != accOwnerId){
					if(userPermssions.containsKey(u_at.UserId)){
						AccountShare old_ashare = userPermssions.get(u_at.UserId);
						old_ashare.AccountAccessLevel = compareLevel(old_ashare.AccountAccessLevel, u_at.AccountAccessLevel);
						old_ashare.OpportunityAccessLevel = compareLevel(old_ashare.OpportunityAccessLevel, u_at.OpportunityAccessLevel);
						old_ashare.CaseAccessLevel    = compareLevel(old_ashare.CaseAccessLevel, u_at.CaseAccessLevel);
						upsertAccShrs.add(old_ashare);					
					}else{
						AccountShare new_ashare = new AccountShare();
						new_ashare.AccountId = this.accId;
						new_ashare.UserOrGroupId = u_at.UserId;
						new_ashare.AccountAccessLevel = compareLevel(READ, u_at.AccountAccessLevel);
						new_ashare.OpportunityAccessLevel = compareLevel(None, u_at.OpportunityAccessLevel);
						new_ashare.CaseAccessLevel    = compareLevel(None, u_at.CaseAccessLevel);
						upsertAccShrs.add(new_ashare);	 
					}
				}
			}
			try{
				insert newAccTeams;
				upsert upsertAccShrs;
			}catch(Exception ex){
				addError(ex.getMessage());
				GeneralConstants.mailAnyExceptionToMe('VFPageAccountTeam :','VF page : insert account team Fail', ex);
			}
		}
		return null;
	}
		
	public PageReference addDefaultOppTeams(){
		if(hasDefaultSalesTeam){
			ID oppOwnerId = [select OwnerId from Opportunity where Id =: oppId limit 1].OwnerId;
			List<UserTeamMember> defaultOppTeams = [select TeamMemberRole, UserId, OpportunityAccessLevel from UserTeamMember where OwnerId =: oppOwnerId];
			Set<String> defaultOppTeamStrs = new Set<String>();
			for(UserTeamMember o : defaultOppTeams){
				defaultOppTeamStrs.add('' + o.UserId + ';' + o.OpportunityAccessLevel + ';' + o.TeamMemberRole);
			}
			upsertOppTeams(defaultOppTeamStrs, oppOwnerId);
		}
		return null;
	}

	public PageReference addOppTeamsFromParentAccTeams(){
		Opportunity o = [select AccountId, OwnerId from Opportunity where Id =: oppId limit 1];
		ID accId = o.AccountId;
		ID oppOwnerId = o.OwnerId;
		List<AccountTeamMember> parentAccTeams = [select TeamMemberRole, UserId from AccountTeamMember  where AccountId =: accId and User.IsActive = true];
		List<AccountShare> accShrs = [select OpportunityAccessLevel, UserOrGroupId from AccountShare where AccountId =: accId and RowCause IN: ROW_REASONS];
		Map<ID, String> userPer = new Map<ID, String>();
		for(AccountShare ash : accShrs){
			userPer.put(ash.UserOrGroupId, ash.OpportunityAccessLevel);
		}
		Set<String> defaultAccTeamStrs = new Set<String>();
		for(AccountTeamMember a : parentAccTeams){
			String opp_acclevel = (userPer.get(a.UserId) != null)? userPer.get(a.UserId) : READ;
			defaultAccTeamStrs.add('' + a.UserId + ';' + opp_acclevel + ';' + a.TeamMemberRole);
		}
		upsertOppTeams(defaultAccTeamStrs, oppOwnerId);
		return null;
	}

	private void upsertOppTeams(Set<String> defaultTeamStrs, ID oppOwnerId){
		List<OpportunityTeamMember> newOppTeams = new List<OpportunityTeamMember>();
		List<OpportunityShare> upsertOppShrs = new List<OpportunityShare>();
		if(!defaultTeamStrs.isEmpty()){
			List<OpportunityShare> oppShrs = [select OpportunityAccessLevel, UserOrGroupId from OpportunityShare where OpportunityId =: oppId and RowCause IN: ROW_REASONS];
			Map<ID, OpportunityShare> userPermssions = new Map<ID, OpportunityShare>();
			for(OpportunityShare o_shr : oppShrs){
				userPermssions.put(o_shr.UserOrGroupId, o_shr);
			}
			for(String s : defaultTeamStrs){
				OpportunityTeamMember new_oteam = new OpportunityTeamMember();
				String[] ss = s.split(';', 3);
				String u_UserId = ss[0];
				String u_OpportunityAccessLevel = ss[1];
				String u_TeamMemberRole = ss[2];
				new_oteam.OpportunityId = this.oppId;
				new_oteam.TeamMemberRole = u_TeamMemberRole;
				new_oteam.UserId = u_UserId;
				newOppTeams.add(new_oteam);
				
				if(u_UserId != oppOwnerId){
					if(userPermssions.containsKey(u_UserId)){
						OpportunityShare old_oshare = userPermssions.get(u_UserId);
						old_oshare.OpportunityAccessLevel = compareLevel(old_oshare.OpportunityAccessLevel, u_OpportunityAccessLevel);
						upsertOppShrs.add(old_oshare);					
					}else{
						OpportunityShare new_oshare = new OpportunityShare();
						new_oshare.OpportunityId = this.oppId;
						new_oshare.UserOrGroupId = u_UserId;
						new_oshare.OpportunityAccessLevel = compareLevel(READ, u_OpportunityAccessLevel);
						upsertOppShrs.add(new_oshare);	 
					}
				}
			}
			try{
				insert newOppTeams;
				upsert upsertOppShrs;
			}catch(Exception ex){
				addError(ex.getMessage());
				GeneralConstants.mailAnyExceptionToMe('VFPageAccountTeam :','VF page : insert opportunity team Fail', ex);
			}	
		}	
	}
	
	public String getNO_SPLIT(){
		return NO_SPLIT;
	}
	
	public PageReference deleteOppTeam(){
		Id delOppTeamId = ApexPages.currentPage().getParameters().get('delOppTeam_Id');
		PageReference pg = new PageReference('/' + this.oppId);
		if(answer == TRUE_Val){
			for(oppTeam o : oppTeams){
				if(o.ot.Id == delOppTeamId){
					if(o.Split == ''){	
						delete o.ot;	
					}else if(o.Split == NO_SPLIT){
						List<OpportunitySplit> delOppSplit = [select Id from OpportunitySplit where OpportunityId =: oppId and SplitOwnerId =: o.ot.UserId];
						delete delOppSplit;
						delete o.ot;	
					}else{
						String trimOppId = String.valueOf(this.oppId).substring(0,15); 
						String trimOppTeamId = String.valueOf(o.ot.Id).substring(0,15); 
						pg = new PageReference('/ui/opportunity/OpportunitySalesTeamEdit/e?oppid=' + trimOppId + '&mdid=' + trimOppTeamId + '&retURL=%2F' + this.oppId);					                                                                         
					}			
					break;
				}
			}
		}
		pg.setRedirect(true);
		return pg;
	}
		
	public PageReference deleteAllOppTeam(){
		List<OpportunitySplit> delOppSplits = [select Id from OpportunitySplit where OpportunityId =: oppId];
		List<OpportunityTeamMember> delOppTeams = [select Id from OpportunityTeamMember where OpportunityId =: oppId];
		try{
			delete delOppSplits;
			delete delOppTeams;
		}catch(Exception ex){
			addError(ex.getMessage());
			GeneralConstants.mailAnyExceptionToMe('VFPageAccountTeam :','VF page : delete all opp team Fail', ex);
		}
		return null;
	}

	public PageReference editAllOppTeam(){
		return null;
	}

    private String compareLevel(String perOld, String perNew){
    	String rst =  (levels.get(perOld) > levels.get(perNew))? perOld : perNew;
    	if(rst == ALL){
			rst = EDIT;
		}
		return rst;
    }
	
    private void addError(String errorMsg){         
        ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.ERROR,errorMsg);               
        ApexPages.addMessage(msg);
    }
    	        	
    private void addInfo(String warningMsg){         
        ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.INFO,warningMsg);               
        ApexPages.addMessage(msg);
    } 
}